package com.spider.admin.logs.service;

import com.spider.admin.cache.ServiceInfoCacheUtil;
import com.spider.admin.cache.ServiceLogSettingsCacheUtil;
import com.spider.admin.conf.StructVar;
import com.spider.admin.exception.SpiderException;
import com.spider.admin.http.entity.PageResult;
import com.spider.admin.logs.model.LogDocument;
import com.spider.admin.logs.util.EsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class LogIndexService {

    @Autowired
    private EsUtil esUtil;

    @Autowired
    private com.spider.admin.service.service.Service service;

    @Autowired
    private ServiceInfoCacheUtil serviceInfoCacheUtil;

    @Autowired
    private ServiceLogSettingsCacheUtil serviceLogSettingsCacheUtil;

    /**
     * 插入日志信息索引
     *
     * @param logList
     * @return
     * @throws SpiderException
     */
    public boolean insertLogsIndex(List<LogDocument> logList) throws SpiderException {

        boolean bol = false;
        if (logList != null && logList.size() > 0) {
            String tempDateStr = null;
            Map<String, String> serviceInfo = null;
            Map<String, String> logSettings = null;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
            for (LogDocument logDoc : logList) {
                tempDateStr = sdf.format(logDoc.getRequestTime());
                serviceInfo = serviceInfoCacheUtil.get(logDoc.getCallServiceRealUrl());
                if (serviceInfo != null && !serviceInfo.isEmpty()) {
                    logDoc
                            .setPubTenantId(serviceInfo.get(ServiceInfoCacheUtil.TENANT_ID))
                            .setPubTenantName(serviceInfo.get(ServiceInfoCacheUtil.TENANT_NAME))
                            .setAppId(serviceInfo.get(ServiceInfoCacheUtil.APPLICATION_ID))
                            .setAppName(serviceInfo.get(ServiceInfoCacheUtil.APPLICATION_NAME))
                            .setServiceId(serviceInfo.get(ServiceInfoCacheUtil.SERVICE_ID))
                            .setServiceName(serviceInfo.get(ServiceInfoCacheUtil.SERVICE_NAME));
                }
                logDoc.setReqDate(tempDateStr);

                //日志采集配置数据转换
                String setting = null;
                String transValue = null;
                logSettings = serviceLogSettingsCacheUtil.get(logDoc.getCallServiceRealUrl());
                if (logSettings != null && !logSettings.isEmpty()) {
                    for (String key : logSettings.keySet()) {
                        setting = logSettings.get(key);
                        switch (key) {
                            case "bizEventId": {
                                if (setting.startsWith(LogSettingTransferUtil.HEADER)) {
                                    transValue = LogSettingTransferUtil.transForHeaders(logDoc.getReqHeaders(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.BODY)) {
                                    transValue = LogSettingTransferUtil.transForBody(logDoc.getReqBody(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PARAMS)) {
                                    transValue = LogSettingTransferUtil.transForParams(logDoc.getReqParams(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PATH)) {
                                    transValue = LogSettingTransferUtil.transForPath(logDoc.getRequestUrl(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.STATIC)) {
                                    transValue = LogSettingTransferUtil.transForStatic(setting);
                                }
                                logDoc.setBizEventId(transValue);
                                break;
                            }
                            case "bizEventType": {
                                if (setting.startsWith(LogSettingTransferUtil.HEADER)) {
                                    transValue = LogSettingTransferUtil.transForHeaders(logDoc.getReqHeaders(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.BODY)) {
                                    transValue = LogSettingTransferUtil.transForBody(logDoc.getReqBody(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PARAMS)) {
                                    transValue = LogSettingTransferUtil.transForParams(logDoc.getReqParams(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PATH)) {
                                    transValue = LogSettingTransferUtil.transForPath(logDoc.getRequestUrl(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.STATIC)) {
                                    transValue = LogSettingTransferUtil.transForStatic(setting);
                                }
                                logDoc.setBizEventType(transValue);
                                break;
                            }
                            case "mdTypeCode": {
                                if (setting.startsWith(LogSettingTransferUtil.HEADER)) {
                                    transValue = LogSettingTransferUtil.transForHeaders(logDoc.getReqHeaders(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.BODY)) {
                                    transValue = LogSettingTransferUtil.transForBody(logDoc.getReqBody(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PARAMS)) {
                                    transValue = LogSettingTransferUtil.transForParams(logDoc.getReqParams(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PATH)) {
                                    transValue = LogSettingTransferUtil.transForPath(logDoc.getRequestUrl(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.STATIC)) {
                                    transValue = LogSettingTransferUtil.transForStatic(setting);
                                }
                                logDoc.setMdTypeCode(transValue);
                                break;
                            }
                            case "mdId": {
                                if (setting.startsWith(LogSettingTransferUtil.HEADER)) {
                                    transValue = LogSettingTransferUtil.transForHeaders(logDoc.getReqHeaders(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.BODY)) {
                                    transValue = LogSettingTransferUtil.transForBody(logDoc.getReqBody(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PARAMS)) {
                                    transValue = LogSettingTransferUtil.transForParams(logDoc.getReqParams(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.PATH)) {
                                    transValue = LogSettingTransferUtil.transForPath(logDoc.getRequestUrl(), setting);
                                } else if (setting.startsWith(LogSettingTransferUtil.STATIC)) {
                                    transValue = LogSettingTransferUtil.transForStatic(setting);
                                }
                                logDoc.setMdId(transValue);
                                break;
                            }
                            default:
                                break;
                        }
                    }
                }
            }
            bol = esUtil.insertListEs(StructVar.LOG_INDEX_NAME, logList);
        }
        if (!bol) {
            log.info("插入索引数据失败");
        }
        return bol;
    }

    /**
     * 目前支持 汉字、拼音全拼、拼音缩写、汉字拼音混合搜索人员姓名。
     * 如果后期需要增加其他的查询条件，在此方法构建即可。
     * 如果有其他的字段有需求需要更改索引的 Mapping。详细可以参考一下 doc目录下的 ES人员信息索引维护.docx
     *
     * @return
     * @throws SpiderException
     */
    public PageResult<LogDocument> searchLogs(String pubTenantId, String callTenantId, Integer page, Integer pageSize, String appName, String serviceName, String startCallDate, String endCallDate) throws SpiderException {
        // 查询条件
        page = page == null ? 1 : page.intValue();
        pageSize = pageSize == null ? StructVar.LOGS_DEFAULT_PAGE_SIZE : pageSize.intValue();
        PageResult<LogDocument> pageResult = new PageResult<>();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        if (StringUtils.isNotEmpty(startCallDate) && StringUtils.isNotEmpty(endCallDate)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
            try {
                Date eDate = sdf.parse(endCallDate);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(eDate);
                calendar.add(Calendar.HOUR_OF_DAY, 32);
                Date newDate = calendar.getTime();
                endCallDate = sdf.format(newDate);
            } catch (Exception e) {
            }
            try {
                Date eDate = sdf.parse(startCallDate);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(eDate);
                calendar.add(Calendar.HOUR_OF_DAY, 8);
                Date newDate = calendar.getTime();
                startCallDate = sdf.format(newDate);
            } catch (Exception e) {
            }
//            startCallDate = startCallDate.replace(startCallDate.substring(startCallDate.indexOf("T")), "T00:00:00.000+08:00");
//            endCallDate = endCallDate.replace(endCallDate.substring(endCallDate.indexOf("T")), "T00:00:00.000+08:00");
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("reqDate")
                    .gte(startCallDate) // 起始时间
                    .lt(endCallDate); // 结束时间
            boolQueryBuilder.must(rangeQueryBuilder);
        }
        if (StringUtils.isNotEmpty(appName)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("appName", appName));
        }
        if (StringUtils.isNotEmpty(serviceName)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("serviceName", serviceName));
        }
        if (StringUtils.isNotEmpty(pubTenantId)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("pubTenantId", pubTenantId));
        }
        if (StringUtils.isNotEmpty(callTenantId)) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("tenantId", callTenantId));
        }

        long totalCount = esUtil.searchTotalNum(StructVar.LOG_INDEX_NAME, boolQueryBuilder);
        int totalPage = (int) Math.ceil((double) totalCount / (double) pageSize);
        Map<String, org.elasticsearch.search.sort.SortOrder> sortMap = new HashMap<>();
        sortMap.put("reqDate", SortOrder.DESC);
        pageResult
                .setCurrentPage(page)
                .setPageSize(pageSize)
                .setTotal(totalCount)
                .setTotalPage(totalPage)
                .setList(esUtil.search(StructVar.LOG_INDEX_NAME, page, pageSize, boolQueryBuilder, sortMap, LogDocument.class));
        return pageResult;
    }
}
